#include "rdx_basictypes.hpp"

namespace RDX
{
	namespace Utility
	{
		bool IsDigit(Char c)
		{
			return (c >= '0' && c <= '9');
		}

		Float64 StringToDouble(const Char *chars, LargeUInt len)
		{
			const Char *endpoint = chars + len;
			Float64 fv = 0.0;
			Int32 decimalShift = 0;
			Char lastC = 0;
			bool negateAll = false;

			if(chars != endpoint)
			{
				lastC = *chars++;
				if(lastC == '-')
					negateAll = true;
			}

			while(true)
			{
				if(!IsDigit(lastC))
					break;
				if(negateAll)
					fv = fv * 10.0 - (lastC - '0');
				else
					fv = fv * 10.0 + (lastC - '0');

				if(chars == endpoint)
					break;
				lastC = *chars++;
			}

			if(lastC == '.')
			{
				while(true)
				{
					if(chars == endpoint)
						break;
					lastC = *chars++;
					if(!IsDigit(lastC))
						break;
					if(negateAll)
						fv = fv * 10.0 - (lastC - '0');
					else
						fv = fv * 10.0 + (lastC - '0');
					decimalShift--;
				}
			}
			if(lastC == 'e')
			{
				Int32 exponent = 0;
				bool negate;
				if(chars != endpoint)
				{
					lastC = *chars++;
					if(lastC == '-')
					{
						negate = true;
						if(chars != endpoint)
							lastC = *chars++;
					}

					while(true)
					{
						if(!IsDigit(lastC))
							break;
						if(negate)
							exponent = exponent * 10 - (lastC - '0');
						else
							exponent = exponent * 10 + (lastC - '0');
						if(chars == endpoint)
							break;
						lastC = *chars++;
					}
				}

				decimalShift += exponent;

				if(decimalShift == 0x8000000)
					fv = 0.0;
				else if(decimalShift == 0)
				{
					// Nothing
				}
				else if(decimalShift < 0)
				{
					decimalShift = -decimalShift;
					Float64 power = 10.0;
					Float64 expMul = 1.0;
					for(int i=0;i<32;i++)
					{
						power *= power;
						if(decimalShift & (1 << i))
							expMul *= power;
					}
					fv /= expMul;
				}
				else
				{
					Float64 power = 10.0;
					Float64 expMul = 1.0;
					for(int i=0;i<32;i++)
					{
						power *= power;
						if(decimalShift & (1 << i))
							expMul *= power;
					}
					fv *= expMul;
				}
			}

			return fv;
		}
	}
}
